package com.gao.d_selector.e;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * @author gao
 * @time 2020/08/11 21:46:24
 */
public class Client {
    private Selector selector;
    private SocketChannel channel;
    private int port;
    public Client(int port) throws IOException {
        this.port = port;
        selector = Selector.open();
        channel = SocketChannel.open();
        channel.configureBlocking(false);
    }

    public void start() {
        try {
            boolean bb = channel.connect(new InetSocketAddress(port));
            if (!bb) {
                channel.register(selector, SelectionKey.OP_CONNECT);
            }
            while (true) {
                int n = selector.select();
                System.out.println("client: select() returned...");
                if (n > 0) {
                    Set<SelectionKey> selectedKeys = selector.selectedKeys();
                    Iterator<SelectionKey> it = selectedKeys.iterator();
                    while (it.hasNext()) {
                        SelectionKey key = it.next();
                        it.remove();
                        if (key.isValid() && key.isConnectable()) {
                            connect(key);
                        }
                        if (key.isValid() && key.isWritable()) {
                            write(key);
                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private void write(SelectionKey key) {
        try {

            /*
                客户端连续发送多条消息
                1. 客户端发送的消息长度为65，当服务端接受消息的ByteBuffer大小为100（超过65），就"有可能"出现粘包的现象
                2. 客户端发送的消息长度为65，当服务端接受消息的ByteBuffer大小为50（小过65），就"一定会"出现断包的现象
             */
            for (int i = 1; i <= 10; i++) {
                SocketChannel channel = (SocketChannel) key.channel();
                // the msg'length is 65
                String msg = i+ " There is no royal road to learning,it is never too old to learn";
                ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes());

                channel.write(buffer);

                System.out.println("send msg to serverver: " + msg);
            }
            key.cancel();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void connect(SelectionKey key) {
        try {
            SocketChannel channel = (SocketChannel) key.channel();
            boolean b = channel.finishConnect();
            if (b) {
                System.out.println("connect to server...");
                channel.register(selector, SelectionKey.OP_WRITE);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws IOException {
        Client client = new Client(8888);
        client.start();
    }
}
